package fr.bda.cloud.tray;

import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import fr.bda.cloud.storage.LocalStorageUnitConfiguration;
import fr.bda.cloud.storage.StorageUnitConfiguration;
import fr.bda.cloud.tray.file.ReadFileDialog;
import fr.bda.cloud.tray.file.ReadFileDialogController;
import fr.bda.cloud.tray.file.SaveFileDialog;
import fr.bda.cloud.tray.file.SaveFileDialogController;
import fr.bda.cloud.tray.storage.NewStorageUnitDialog;
import fr.bda.cloud.tray.storage.NewStorageUnitDialogController;

public class CloudTray implements CloudTrayDialogListener {

	private static final String TITLE = "Cloud Tray";
	private static final Image SYSTRAY_ICON = Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource("SystrayIcon.png"));
	private static final Image SYSTRAY_ICON_WARNING = Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource("SystrayIconWarning.png"));
	private final Object dialSyncObject = new Object();
	private CloudTrayDialog<?> dial = null;
	private File workingDir = new File(".");

	private SystemTray tray;
	private TrayIcon trayIcon = null;
	private JAXBContext jaxbContext;
	private CloudTrayData data = new CloudTrayData();
	private List<CloudTrayDialogController> dialogControllers = new ArrayList<>();

	public CloudTray() {

		try {
			jaxbContext = JAXBContext.newInstance(CloudTrayData.class, StorageUnitConfiguration.class, LocalStorageUnitConfiguration.class);
		} catch (JAXBException e1) {
			e1.printStackTrace();
		}

		if (SystemTray.isSupported()) {

			PopupMenu popup = new PopupMenu();
			MenuItem menuLogin = new MenuItem("Login...");
			MenuItem menuStorageUnit = new MenuItem("Storage unit...");
			MenuItem menuSaveFile = new MenuItem("Save file...");
			MenuItem menuReadFile = new MenuItem("Read file...");
			MenuItem menuExit = new MenuItem("Exit");

			popup.add(menuLogin);
			popup.add(menuStorageUnit);
			popup.add(menuSaveFile);
			popup.add(menuReadFile);
			popup.add(menuExit);

			menuLogin.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					synchronized (dialSyncObject) {

					}
				}
			});

			menuStorageUnit.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					synchronized (dialSyncObject) {
						if (dial == null) {
							dial = new NewStorageUnitDialog(CloudTray.this, new NewStorageUnitDialogController(CloudTray.this));
							dial.setVisible(true);
						}
					}
				}
			});

			menuSaveFile.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					synchronized (dialSyncObject) {
						if (dial == null) {
							dial = new SaveFileDialog(CloudTray.this, new SaveFileDialogController(CloudTray.this));
							dial.setVisible(true);
						}
					}
				}
			});

			menuReadFile.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					if (dial == null) {
						dial = new ReadFileDialog(CloudTray.this, new ReadFileDialogController(CloudTray.this));
						dial.setVisible(true);
					}
				}
			});

			menuExit.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					System.exit(0);
				}
			});

			tray = SystemTray.getSystemTray();
			trayIcon = new TrayIcon(SYSTRAY_ICON, TITLE, popup);
			trayIcon.setImageAutoSize(true);
			try {
				tray.add(trayIcon);
			} catch (AWTException e) {
				System.err.println(e);
			}

		} else {
			System.err.println("SystemTray not supported");
		}

		loadData();

		initDialogControllers();

		if ("admin".equals(data.getUser().getLogin())) {
			tray.getTrayIcons()[0].setToolTip(TITLE + " - admin account");
			tray.getTrayIcons()[0].setImage(SYSTRAY_ICON_WARNING);
		}
	}

	private void initDialogControllers() {
		dialogControllers.add(new NewStorageUnitDialogController(this));
		dialogControllers.add(new SaveFileDialogController(this));
		dialogControllers.add(new ReadFileDialogController(this));
	}

	@Override
	public <C extends CloudTrayDialogController> void onDialogInit(CloudTrayDialog<C> dialog) {

	}

	@Override
	public <C extends CloudTrayDialogController> void onDialogValid(CloudTrayDialog<C> dialog) {
		dial = null;
	}

	@Override
	public <C extends CloudTrayDialogController> void onDialogCancel(CloudTrayDialog<C> dialog) {
		dial = null;
	}

	public void saveData() {
		System.out.println("Save in [" + workingDir.getAbsolutePath() + "]");
		try (FileOutputStream fos = new FileOutputStream(new File(workingDir, "CloudTray.xml"));) {
			Marshaller marshaller = jaxbContext.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			marshaller.marshal(data, fos);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}

	public void loadData() {
		File dataFile = new File(workingDir, "CloudTray.xml");
		if (dataFile.exists()) {
			try {
				data = (CloudTrayData) jaxbContext.createUnmarshaller().unmarshal(dataFile);
			} catch (JAXBException e) {
				e.printStackTrace();
			}
		}
	}

	public CloudTrayData getData() {
		return data;
	}

	public static void main(String[] args) {
		new CloudTray();
	}

}
